`timescale 1ns / 1ps

`include "MIPSCPU_COMMON.vh"

module ALU(
	op_subtype,
	value1,
	value2,
	out_result
    );

	input[`OPERATION_SUBTYPE_WIDTH - 1 : 0] op_subtype;
	input[`DATA_WIDTH - 1 : 0] value1, value2;
	output reg[`DATA_WIDTH - 1 : 0] out_result;
	
	always @(*)
	begin
		case (op_subtype)
			`OPERATION_SUBTYPE_GET:
				out_result <= value1;
			`OPERATION_SUBTYPE_EQUAL:
				out_result <= (value1 == value2 ? 1 : 0);
			`OPERATION_SUBTYPE_NOT_EQUAL:
				out_result <= (value1 != value2 ? 1 : 0);
			`OPERATION_SUBTYPE_LESS:
				out_result <= ($signed(value1) < $signed(value2) ? 1 : 0);
			`OPERATION_SUBTYPE_LESS_UNSIGNED:
				out_result <= ($unsigned(value1) < $unsigned(value2) ? 1 : 0);
			`OPERATION_SUBTYPE_LESS_EQUAL:
				out_result <= ($signed(value1) <= $signed(value2) ? 1 : 0);
			`OPERATION_SUBTYPE_GREATER:
				out_result <= ($signed(value1) > $signed(value2) ? 1 : 0);
			`OPERATION_SUBTYPE_GREATER_EQUAL:
				out_result <= ($signed(value1) >= $signed(value2) ? 1 : 0);
			`OPERATION_SUBTYPE_AND:
				out_result <= value1 & value2;
			`OPERATION_SUBTYPE_OR:
				out_result <= value1 | value2;
			`OPERATION_SUBTYPE_XOR:
				out_result <= value1 ^ value2;
			`OPERATION_SUBTYPE_NOR:
				out_result <= ~(value1 | value2);
			`OPERATION_SUBTYPE_ADD:
				out_result <= value1 + value2;
			`OPERATION_SUBTYPE_SUB:
				out_result <= value1 - value2;
			`OPERATION_SUBTYPE_SLL:
				out_result <= value1 << value2;
			`OPERATION_SUBTYPE_SRA:
				out_result <= $signed(value1) >>> value2;
			`OPERATION_SUBTYPE_SRL:
				out_result <= $unsigned(value1) >> value2;
			default: out_result <= 0;
		endcase
	end

endmodule
